#include <iostream>        
#include <thread>             
#include <mutex>              
#include <condition_variable> 

std::mutex mtx;
std::condition_variable cv;
bool ready = false;

void print_id (int id) {
    std::unique_lock<std::mutex> lck(mtx);
    // 只要当前ready等于false，都会进入等待
    while (!ready) 
        cv.wait(lck);

    std::cout << "thread " << id << '\n';
}

void go() {
    std::unique_lock<std::mutex> lck(mtx);
    // 将reaedy置为true，同时唤醒所有线程
    ready = true;
    cv.notify_all();
}

// int main ()
// {
//     std::thread threads[10];
//     // spawn 10 threads:
//     for (int i=0; i<10; ++i)
//         threads[i] = std::thread(print_id,i);

//     std::cout << "10 threads ready to race...\n";
//     // 主线程先睡眠100微秒，等待所有的线程都被阻塞
//     std::this_thread::sleep_for(std::chrono::microseconds(100));
//     go();                       // go!

//     for (auto& th : threads) th.join();

//     return 0;
// }

// void two_thread_print() {
//     std::mutex mtx;
//     int n = 100;
//     bool flag = true;
//     std::condition_variable cv;
//     // 让t1打印偶数，t2打印奇数
//     // 并且让t2先创建t1后创建

//     std::thread t2([&]() {
//         int i = 1;
//         while (i < n) {
//             std::unique_lock<std::mutex> lock(mtx);
//             // 只要flag当前为true就会阻塞
//             while (flag) 
//                 cv.wait(lock);
//             std::cout << i << std::endl;
//             // 运行到这一步说明flag的值为false
//             // 修改flag的值让t1线程运行
//             flag = true;
//             i += 2;
//             // 唤醒在睡眠的t1线程
//             cv.notify_one();
//         }
//     });

//     std::this_thread::sleep_for(std::chrono::microseconds(1000));

//     std::thread t1([&]() {
//         int i = 0;
//         while (i < n) {
//             std::unique_lock<std::mutex> lock(mtx);
//             while (!flag) 
//                 cv.wait(lock);
//             std::cout << i << std::endl;
//             // 运行到这一步说明flag的值为true
//             // 修改flag的值让t2线程运行
//             flag = false;
//             i += 2;
//             // 唤醒在睡眠的t2线程
//             cv.notify_one();
//         }
//     });

//     t1.join();
//     t2.join();
// }

// int main() {
//     two_thread_print();
//     return 0;
// }

// double Division(int a, int b) {
//     // 当b == 0时抛出异常
//     if (b == 0) {
//         //// 若是throw这个string变量，则会在func函数中直接捕获
//         throw std::string("Division by zero condition!");  

//         // 若是throw这个const char*变量，则会在main函数中捕获
//         // throw "Division by zero condition!";
//     } else {
//         return ((double)a / (double)b);
//     }
// }

// void Func() {
//     try {
//         int len, time;
//         std::cin >> len >> time;
//         std::cout << Division(len, time) << std::endl;
//     } catch (const std::string& errstr) {
//         std::cout << errstr << std::endl;
//     }
//     // 若在这层捕获到异常或者没有发生异常
//     // 都会执行下面这一句
//     std::cout << "xxxxxxxxxxx" << std::endl;
// }

// int main()
// {
//     try {
//         Func();
//     } catch (const char *errmsg) {
//         std::cout << errmsg << std::endl;
//     } catch (...) {
//         std::cout << "unkown exception" << std::endl;
//     }
//     return 0;
// }

// double Division(int a, int b)
// {
//     // b == 0时抛出异常
//     if (b == 0) 
//         throw "Division by zero condition!";
    
//     return (double)a / (double)b;
// }

// void Func()
// {
//     // 这里可以看到如果发生除0错误抛出异常，另外下面的array没有得到释放。
//     // 所以这里捕获异常后并不处理异常，异常还是交给外面处理，这里捕获了再
//     // 重新抛出去。
//     int *array = new int[10];
//     try {
//         int len, time;
//         std::cin >> len >> time;
//         std::cout << Division(len, time) << std::endl;
//     } catch (...) {
//         std::cout << "delete []" << array << std::endl;
//         delete[] array;
//         throw;
//     }
//     // ...
//     std::cout << "delete []" << array << std::endl;
//     delete[] array;
// }

// int main() {
//     try {
//         Func();
//     } catch (const char *errmsg) {
//         std::cout << errmsg << std::endl;
//     }
//     return 0;
// }